<?php

	/**
	 * @see Bike_Js_Base
	 */
	require_once 'Bike/Js/Base.php';
	
	
	class Bike_Js_Expression extends Bike_Js_Base
	{
        const NO_VALUE = '#@NO_VALUE@#';

        public function makeOptions(array $Args=null)
		{
			$options = $Args;
			return $options;
		}

        protected function addPart($PreOperator, $Value='', $PostOperator='')
		{			if(!is_array($this->_settings))
			{				$this->_settings = array();
			}
			array_push($this->_settings, array(
				'preOperator' => $PreOperator,
				'value' => $Value,
				'postOperator' => $PostOperator
			));
			return $this;
		}

		public function _value()
		{			$args = func_get_args();
			$Value = array_shift($args);
			$DefaultFlag = False;
			if(sizeof($args))
			{
				$Default = array_shift($args);
				$DefaultFlag = True;
			}
			$this->addPart('=', $Value);
			if($DefaultFlag)
			{				$this->addPart('||', $Default);
			}
			return $this;
		}

		public function __call($MethodName, array $Args=null)
		{
            $operator = '';
            $preOperator = True;
            $useArgs = (!is_null(@$Args[0])) ? True : False;
			switch($MethodName)
			{
				case '_add': 		$operator = '+'; break;
				case '_sub': 		$operator = '-'; break;
				case '_div': 		$operator = '/'; break;
				case '_mult': 		$operator = '*'; break;
				case '_inc': 		$operator = '++'; $preOperator = False; break;
				case '_dec': 		$operator = '--'; $preOperator = False; break;
				case '_preInc': 	$operator = '++'; break;
				case '_preDec': 	$operator = '--'; break;
				case '_var': 		$operator = 'var '; break;
				case '_new': 		$operator = 'new '; break;
				case '_valNew': 	$operator = '=new '; break;
				case '_val': 		return call_user_func_array(array($this,'_value'), $Args);
				case '_eq': 		$operator = '=='; break;
				case '_neq': 		$operator = '!='; break;
				case '_gt': 		$operator = '>'; break;
				case '_lt': 		$operator = '<'; break;
				case '_gte': 		$operator = '>='; break;
				case '_lte': 		$operator = '<='; break;
				case '_identity': 	$operator = '==='; break;
				case '_instanceof': $operator = ' instanceof '; break;
				case '_in': 		$operator = ' in '; break;
				case '_notIdentity': 	$operator = '!=='; break;
				case '_not': 		$operator = '!'; $useArgs = True; break;
				case '_and': 		$operator = '&&'; $useArgs = True; break;
				case '_or': 		$operator = '||'; $useArgs = True; break;
				case '_compare': 	$operator = array_shift($Args); break;
				case '_isUndefined': 	return $this->_identity($this->js()->undefined);
				case '_isNotUndefined': return $this->_notIdentity($this->js()->undefined);
				default:
					if(!in_array(substr($MethodName, 0, 3), array('set', 'get')))
					{
						require_once 'Bike/Js/Exception.php';
						throw new Bike_Js_Exception(sprintf('Method "%s" is undefined', $MethodName));
					}

			}
			return $this->addPart(($preOperator ? $operator : ''), (($useArgs) ? array_shift($Args) : self::NO_VALUE), (!$preOperator ? $operator : ''));
		}

		public function _toString()
		{
			$settings = array();
			foreach($this->_settings as $setting)
			{				$Value = $this->_prepareValue($setting['value']);
				$PreOperator = $setting['preOperator'];
				$PostOperator = $setting['postOperator'];
				$preLen = strlen($PreOperator);
				$postLen = strlen($PostOperator);
				if($PreOperator && substr($Value, 0, $preLen) == $PreOperator)
				{					$PreOperator = '';
				}
				if($PostOperator && substr($Value, -$postLen) == $PostOperator)
				{
					$PostOperator = '';
				}
				array_push($settings, $PreOperator.(($setting['value'] === self::NO_VALUE)	? '' : $Value).$PostOperator);
			}
			return join('', $settings);
		}
	}
